feat(agent): implement package broker#1847
feat(agent): implement package broker#1847Vladyslav Nikonov (vnikonov-devolutions) wants to merge 3 commits into
Conversation
Let maintainers know that an action is required on their side
|
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2158cf9 to
83fa0b1
Compare
There was a problem hiding this comment.
Pull request overview
Implements an early Windows package broker for Devolutions Agent.
Changes:
- Adds policy loading, evaluation, live reload, and sample scenarios.
- Adds authenticated named-pipe APIs, operation tracking, and status polling.
- Adds WinGet/PowerShell command builders and elevated execution.
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 24 comments.
Show a summary per file
| File | Description |
|---|---|
.gitattributes |
Adds asset and YAML attributes. |
Cargo.lock |
Locks new broker dependencies. |
devolutions-agent/Cargo.toml |
Adds broker dependencies and Windows features. |
devolutions-agent/src/lib.rs |
Exposes Windows broker modules. |
devolutions-agent/src/service.rs |
Starts the configured broker task. |
devolutions-agent/src/config.rs |
Adds broker and debug configuration. |
devolutions-agent/src/code_signing.rs |
Centralizes signature validation. |
devolutions-agent/src/updater/package.rs |
Reuses signature helpers. |
devolutions-agent/src/broker/mod.rs |
Defines broker modules. |
devolutions-agent/src/broker/auth.rs |
Authenticates pipe clients. |
devolutions-agent/src/broker/task.rs |
Coordinates broker subsystems. |
devolutions-agent/src/broker/pipe.rs |
Implements named-pipe transport. |
devolutions-agent/src/broker/policy_loader.rs |
Loads JSON/YAML policies. |
devolutions-agent/src/broker/policy_watcher.rs |
Implements policy hot reload. |
devolutions-agent/src/broker/operation_tracker.rs |
Tracks asynchronous operations. |
devolutions-agent/src/broker/server/mod.rs |
Implements broker API behavior. |
devolutions-agent/src/broker/server/connection.rs |
Serves HTTP pipe connections. |
devolutions-agent/src/broker/server/execution.rs |
Runs background operations. |
devolutions-agent/src/broker/server/responses.rs |
Builds API responses. |
devolutions-agent/src/broker/executor/mod.rs |
Defines execution abstractions. |
devolutions-agent/src/broker/executor/output.rs |
Handles output and exit codes. |
devolutions-agent/src/broker/executor/windows/mod.rs |
Implements Windows execution plans. |
devolutions-agent/src/broker/executor/windows/process.rs |
Creates user-token processes. |
devolutions-agent/src/broker/executor/windows/token.rs |
Resolves sessions and tokens. |
devolutions-agent/src/broker/command_builder/mod.rs |
Dispatches command construction. |
devolutions-agent/src/broker/command_builder/winget.rs |
Builds WinGet commands. |
devolutions-agent/src/broker/command_builder/powershell.rs |
Builds PowerShell commands. |
devolutions-agent/src/broker/evaluator/mod.rs |
Implements policy precedence. |
devolutions-agent/src/broker/evaluator/matching.rs |
Matches request attributes. |
devolutions-agent/src/broker/evaluator/constraints.rs |
Enforces rule constraints. |
devolutions-agent/src/broker/evaluator/version.rs |
Matches version ranges. |
devolutions-agent/src/broker/evaluator/wildcard.rs |
Implements wildcard matching. |
devolutions-agent/src/broker/evaluator/tests.rs |
Tests policy evaluation. |
devolutions-agent/src/broker/scenario_tests.rs |
Runs sample scenarios. |
devolutions-agent/src/broker/assets/samples/corporate-allowlist.policy.json |
Adds allowlist policy sample. |
devolutions-agent/src/broker/assets/samples/deny-risky-options.policy.json |
Adds deny-list policy sample. |
devolutions-agent/src/broker/assets/samples/scenarios/baseline.scenarios.json |
Defines baseline scenarios. |
devolutions-agent/src/broker/assets/samples/requests/winget-vscode-install.request.json |
Adds allowed request sample. |
devolutions-agent/src/broker/assets/samples/requests/winget-vscode-skiphash.request.json |
Adds risky request sample. |
devolutions-agent/src/broker/assets/samples/requests/winget-unknown-install.request.json |
Adds denied request sample. |
crates/devolutions-agent-shared/Cargo.toml |
Adds temporary-file dependencies. |
crates/devolutions-agent-shared/src/lib.rs |
Exposes temporary-file utilities. |
crates/devolutions-agent-shared/src/temp_file.rs |
Adds shared temporary-script handling. |
devolutions-session/Cargo.toml |
Removes direct tempfile dependency. |
devolutions-session/src/main.rs |
Removes obsolete dependency import. |
devolutions-session/src/dvc/fs.rs |
Re-exports the shared guard. |
devolutions-session/src/dvc/task.rs |
Uses shared script utilities. |
devolutions-session/src/dvc/process.rs |
Converts I/O execution errors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let policy_path = match &self.config.policy_path { | ||
| Some(path) => std::path::PathBuf::from(path), | ||
| None => policy_loader::find_default_policy().context("failed to find default broker policy")?, |
| }); | ||
|
|
||
| // Bridge the agent's ShutdownSignal to the Notify used by subsystems. | ||
| let shutdown_notify = Arc::new(Notify::new()); |
| async fn status(&self, request: StatusRequest) -> Result<StatusResponse, ErrorResponse> { | ||
| self.state.status(request).await | ||
| } |
| capture_output: request.capture_output, | ||
| }; | ||
|
|
||
| let (operation_id, is_new_operation) = self.tracker.register(&request.request_id, generated_operation_id); |
| if is_new_operation { | ||
| self.tracker.mark_running(&operation_id); | ||
| execution::spawn_execution( |
| Err(error) => { | ||
| error!(%error, "Failed to create policy file watcher"); | ||
| return; | ||
| } |
| if let Err(error) = watcher.watch(&watch_path, RecursiveMode::NonRecursive) { | ||
| error!(%error, path = %watch_path.display(), "Failed to watch policy directory"); | ||
| return; |
| if let Some(version) = request.package.version.as_deref() { | ||
| append_flag_value(&mut script, "-RequiredVersion", version); | ||
| } |
| // Wait for agent shutdown signal. | ||
| shutdown_signal.wait().await; | ||
| info!("package broker received shutdown signal"); | ||
| shutdown_notify.notify_waiters(); |
| match request.operation { | ||
| Operation::Install => { | ||
| if let Some(version) = request.package.version.as_deref() { | ||
| append_flag_value(&mut script, "-Version", version); | ||
| } | ||
| } | ||
| Operation::Update => append_raw(&mut script, "-Force"), | ||
| // Uninstall removes the installed resource without pinning a version. | ||
| Operation::Uninstall => {} | ||
| } |
Implements now package broker (Also see UniGetUI WIP branch Devolutions/UniGetUI#4826)
This is still in early DRAFT, but can be compiled/tested for further development.
Implemented
Not implemented yet
Steps to run this branch:
"PackageBroker":{"Enabled":true, "PolicyPath": "C:/path/to/policy.json"}"__debug__": { "skip_broker_signature_validation": true }UseAgentBrokerfile at%LOCALAPPDATA%/UniGetUI/Configuration(UniGetUI uses file-based config)